/**************************************************************
* Copyright (C) 2023 www.eipflow.com 孙泽伟版权所有(盗版必究)
*
* 作者: 孙泽伟(QQ 1039318332)
* 创建时间: 2023/8/22 7:58:35
* 文件名: SystemSerialNoLogic
* 描述: 编号规则业务逻辑接口实现
* 
* 修改历史
* 修改人：
* 时间：
* 修改说明：
*
**************************************************************/

using EIP.System.Models.Dtos.WorkSheet;

namespace EIP.System.Logic.Impl
{
    /// <summary>
    /// 编号规则业务逻辑接口实现
    /// </summary>
    public class SystemSerialNoLogic : DapperAsyncLogic<SystemSerialNo>, ISystemSerialNoLogic
    {
        #region 构造函数

        private readonly ISystemSerialNoRepository _systemSerialnoRepository;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="systemSerialnoRepository"></param>
        public SystemSerialNoLogic(ISystemSerialNoRepository systemSerialnoRepository)
        {
            _systemSerialnoRepository = systemSerialnoRepository;
        }

        #endregion

        /// <summary>
        /// 保存后，清除用户对应的单号信息
        /// </summary>
        /// <param name="prefix">单据前缀</param>
        /// <param name="UserId">用户Id</param>
        public void Clear(Guid ZeroCodeId, string model)
        {
            using (var fix = new SqlDatabaseFixture())
            {
                var user = EipHttpContext.CurrentUser();
                fix.Db.SystemSerialNoUser.Update(u => u.UserId == user.UserId && u.ZeroCodeId == ZeroCodeId && u.Key == model, new { Value = "" });
            }
        }

        /// <summary>
        /// 获取用户ID、单据前缀
        /// </summary>
        /// <param name="UserId"></param>
        /// <param name="prefix"></param>
        private async Task<OperateStatus<string>> GetUserNo(SqlDatabaseFixture fix, SystemSerialCreateInput input)
        {
            OperateStatus<string> operateStatus = new OperateStatus<string>();
            var user = EipHttpContext.CurrentUser();
            var serialNo = await fix.Db.SystemSerialNo.FindAsync(f => f.ZeroCodeId == input.ZeroCodeId && f.Key == input.Key);
            var serialNoUser = await fix.Db.SystemSerialNoUser.FindAsync(f => f.UserId == user.UserId && f.ZeroCodeId == input.ZeroCodeId && f.Key == input.Key);

            //申请的单号
            if (serialNoUser != null)
            {
                operateStatus.Msg = Chs.Successful;
                operateStatus.Code = ResultCode.Success;
                operateStatus.Data = serialNoUser.Value;
                return operateStatus;
            }

            if (serialNo != null)
            {
                //判断是否重复
                var rules = serialNo.Rule.JsonStringToList<SystemDataBaseColumnsOptionRuleInput>();
                string ruleReturn = string.Empty;
                foreach (var rule in rules)
                {
                    switch (rule.Type)
                    {
                        case "time"://时间
                            ruleReturn += DateTime.Now.ToString(rule.Key);
                            break;
                        case "number"://数量
                                      //不重复
                            if (rule.Repeat.IsNotNullOrEmpty())
                            {
                                //判断是否已经到了需要重新生成
                                string repeatTime = "";
                                switch (rule.Repeat)
                                {
                                    case "day":
                                        repeatTime = DateTime.Now.ToString("yyyyMMdd");
                                        break;
                                    case "month":
                                        repeatTime = DateTime.Now.ToString("yyyyMM");
                                        break;
                                    case "year":
                                        repeatTime = DateTime.Now.ToString("yyyy");
                                        break;
                                    default:
                                        break;
                                }
                                if (serialNo.RepeatTime.IsNullOrEmpty() || serialNo.RepeatTime != repeatTime)
                                {
                                    serialNo.Value = string.Empty;
                                    serialNo.RepeatTime = repeatTime;
                                }
                            }
                            //是否已生成了编号
                            if (serialNo.Value.IsNullOrEmpty())
                            {
                                //生成编号
                                serialNo.Value = rule.BeginNumber.ToString().PadLeft(rule.Length, '0');
                                await fix.Db.SystemSerialNo.UpdateAsync(serialNo);
                            }
                            else
                            {
                                //原有编号加1
                                var numStr = (Convert.ToInt32(serialNo.Value) + 1).ToString().PadLeft(rule.Length, '0');
                                //是否能够继续编号
                                if (numStr.Length > rule.Length)
                                {
                                    if (!rule.Incremental)
                                    {
                                        operateStatus.Code = ResultCode.Error;
                                        operateStatus.Msg = "自动编号超过上限！";
                                        return operateStatus;
                                    }
                                }
                                serialNo.Value = numStr;
                                await fix.Db.SystemSerialNo.UpdateAsync(serialNo);
                            }
                            ruleReturn += serialNo.Value;
                            break;
                        case "field"://字段
                            var value = "";
                            var column = input.Columns.FirstOrDefault(f => f.Key == rule.Key);
                            if (column != null)
                            {
                                value = column.Value.ToString();
                            }
                            ruleReturn += value;
                            break;
                        case "character"://字段
                            ruleReturn += rule.Key;
                            break;
                        default:
                            break;
                    }
                }

                if (serialNoUser == null)
                {
                    SystemSerialNoUser systemSerialNoUser = new SystemSerialNoUser();
                    systemSerialNoUser.SerialNoUserId = CombUtil.NewComb();
                    systemSerialNoUser.ZeroCodeId = input.ZeroCodeId;
                    systemSerialNoUser.Key = input.Key;
                    systemSerialNoUser.UserId = user.UserId;
                    systemSerialNoUser.Value = ruleReturn;
                    systemSerialNoUser.CreateTime = DateTime.Now;
                    systemSerialNoUser.UpdateTime = DateTime.Now;
                    systemSerialNoUser.CreateUserId = user.UserId;
                    systemSerialNoUser.CreateUserName = user.Name;
                    systemSerialNoUser.UpdateUserId = user.UserId;
                    systemSerialNoUser.UpdateUserName = user.Name;
                    await fix.Db.SystemSerialNoUser.InsertAsync(systemSerialNoUser);
                }
                else
                {
                    serialNoUser.Value = ruleReturn;
                    await fix.Db.SystemSerialNoUser.UpdateAsync(serialNoUser);
                }
                operateStatus.Msg = Chs.Successful;
                operateStatus.Code = ResultCode.Success;
                operateStatus.Data = ruleReturn;
                return operateStatus;
            }
            return operateStatus;
        }

        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<OperateStatus<string>> Create(SystemSerialCreateInput input)
        {
            OperateStatus<string> operateStatus = new OperateStatus<string>();
            var user = EipHttpContext.CurrentUser();
            using (var fix = new SqlDatabaseFixture())
            {
                var serialNo = await fix.Db.SystemSerialNo.FindAsync(f => f.ZeroCodeId == input.ZeroCodeId && f.Key == input.Key);
                if (serialNo == null)
                {
                    try
                    {
                        serialNo = new SystemSerialNo();
                        serialNo.SerialNoId = CombUtil.NewComb();
                        serialNo.Rule = input.Rule;
                        serialNo.Key = input.Key;
                        serialNo.ZeroCodeId = input.ZeroCodeId;
                        serialNo.CreateTime = DateTime.Now;
                        serialNo.UpdateTime = DateTime.Now;
                        serialNo.CreateUserId = user.UserId;
                        serialNo.CreateUserName = user.Name;
                        serialNo.UpdateUserId = user.UserId;
                        serialNo.UpdateUserName = user.Name;
                        await fix.Db.SystemSerialNo.InsertAsync(serialNo);
                    }
                    catch (Exception ex)
                    {
                        operateStatus.Msg = ex.Message;
                        return operateStatus;
                    }
                }
                else
                {
                    serialNo.Rule = input.Rule;
                    serialNo.UpdateTime = DateTime.Now;
                    await fix.Db.SystemSerialNo.UpdateAsync(serialNo);
                }

                if (input.UserOccupation)
                {
                    operateStatus = await GetUserNo(fix, input);
                    return operateStatus;
                }
                //判断是否重复
                var rules = serialNo.Rule.JsonStringToList<SystemDataBaseColumnsOptionRuleInput>();
                string ruleReturn = string.Empty;
                foreach (var rule in rules)
                {
                    switch (rule.Type)
                    {
                        case "time"://时间
                            ruleReturn += DateTime.Now.ToString(rule.Key);
                            break;
                        case "number"://数量
                            if (rule.Repeat.IsNotNullOrEmpty())
                            {
                                //判断是否已经到了需要重新生成
                                string repeatTime = "";
                                switch (rule.Repeat)
                                {
                                    case "day":
                                        repeatTime = DateTime.Now.ToString("yyyyMMdd");
                                        break;
                                    case "month":
                                        repeatTime = DateTime.Now.ToString("yyyyMM");
                                        break;
                                    case "year":
                                        repeatTime = DateTime.Now.ToString("yyyy");
                                        break;
                                    default:
                                        break;
                                }
                                if (serialNo.RepeatTime.IsNullOrEmpty() || serialNo.RepeatTime != repeatTime)
                                {
                                    serialNo.Value = string.Empty;
                                    serialNo.RepeatTime = repeatTime;
                                }
                            }
                            //是否已生成了编号
                            if (serialNo.Value.IsNullOrEmpty())
                            {
                                //生成编号
                                serialNo.Value = rule.BeginNumber.ToString().PadLeft(rule.Length, '0');
                                await fix.Db.SystemSerialNo.UpdateAsync(serialNo);
                            }
                            else
                            {
                                //原有编号加1
                                var numStr = (Convert.ToInt32(serialNo.Value) + 1).ToString().PadLeft(rule.Length, '0');
                                //是否能够继续编号
                                if (numStr.Length > rule.Length)
                                {
                                    if (!rule.Incremental)
                                    {
                                        operateStatus.Code = ResultCode.Error;
                                        operateStatus.Msg = "自动编号超过上限！";
                                        return operateStatus;
                                    }
                                }
                                serialNo.Value = numStr;
                                await fix.Db.SystemSerialNo.UpdateAsync(serialNo);
                            }
                            ruleReturn += serialNo.Value;
                            break;
                        case "field"://字段
                            var value = "";
                            var column = input.Columns.FirstOrDefault(f => f.Key == rule.Key);
                            if (column != null)
                            {
                                value = column.Value.ToString();
                            }
                            ruleReturn += value;
                            break;
                        case "character"://字段
                            ruleReturn += rule.Key;
                            break;
                        default:
                            break;
                    }
                }
                operateStatus.Code = ResultCode.Success;
                operateStatus.Msg = Chs.QuerySuccessful;
                operateStatus.Data = ruleReturn;
            }
            return operateStatus;
        }
    }
}